package racaa;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Random;

import agente.MemEAV;

public class MecAprendQ<S,A> {
	
	private MemEAV<S, A, Double> q = new MemEAV<S, A, Double>(0.0);
	private double alfa;
	private double epsilon;
	private double gama;
	private List<A> accoesOrdAleat;
	private A[] accoes;
	
	Random rand = new Random();
	
	public MecAprendQ(A[] accoes, double alfa, double epsilon, double gama){
		this.accoesOrdAleat = Arrays.asList(accoes);
		this.accoes = accoes;
		this.alfa = alfa;
		this.epsilon = epsilon;
		this.gama = gama;
	}
	
	public void assimilar(S s,A a,S sn,double r){
		double qsa = q.get(s,a);
		A aMax = maxAccao(sn);
		double qsaMax = q.get(sn, aMax);
		double qsaNovo = qsa + alfa*(r + gama*qsaMax - qsa);
		q.set(s, a, qsaNovo);
		
		
	}
	
	public A selAccao(S s){
		if(rand.nextDouble()>epsilon)
			return maxAccao(s);
		else
			return gerarAccaoAleat();
	}

	private A maxAccao(S s){
		A aMax = null;
		double qMax = Double.NEGATIVE_INFINITY;
		
		Collections.shuffle(accoesOrdAleat);
		for(A a : accoesOrdAleat){
			double qa = q.get(s,a);
			if(qa > qMax){
				qMax = qa;
				aMax = a;
			}
		}
		return aMax;
	}
	
	private A gerarAccaoAleat(){
		return accoesOrdAleat.get(rand.nextInt(accoesOrdAleat.size()));
	}
	
	public double getMaxQ(S s){
		return q.get(s,q.getAccaoMax(s, accoes));
	}
	
	
	
}
